/*******************************************************************************
 *
 *    Copyright (c) Dolphin Browser
 *
 *    ViewTest
 *
 *    ScrollPageView
 *    TODO File description or class description.
 *
 *    @author: derron
 *    @since:  2010-3-8
 *    @version: 1.0
 *
 ******************************************************************************/
package com.sdk.widget.threescreen.scrollview;


import com.android.sdk.R;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * ScrollPageView of ViewTest.
 *
 * @author derron
 *
 */
public class ScrollableView extends FrameLayout {

    public static interface PageEventObserver {
        public void onLeftPageShown(ScrollPageView paramPageView);
        public void onMiddlePageShown(ScrollPageView paramPageView);
        public void onRightPageShown(ScrollPageView paramPageView);
    }

    public static interface WorldScrollProvider {
        public boolean shouldWorldScroll(int x, int y,int velocityX,int velocityY);
    }

    public static interface PageProvider {
        public boolean requestLeftPage(ScrollPageView pageView);
        public boolean requestRightPage(ScrollPageView pageView);
    }

    private static final int LEFT_BAR_WIDTH = DisplayManager.dipToPixel(240);

    private static final int RIGHT_BAR_WIDTH = DisplayManager.dipToPixel(60);

    private int curPageNumber;

    private int firstShownPageNumber;

    private boolean isPageFirstShown;

    private ScrollableLinearLayout pageContainer;

    private PageEventObserver pageEventObserver;

    private final List<ScrollPageView> pages = new ArrayList<ScrollPageView>();

    private boolean flingable = false;
    private PageProvider pageProvider;
    public void setPageProvider(PageProvider provider) {
        pageProvider = provider;
    }

    public ScrollableView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public ScrollableView(Context context) {
        super(context);
        init(context);
    }

    public ScrollableView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public boolean isScrollable() {
        return pageContainer.isScrollable();
    }

    public void setScrollable(boolean scrollable) {
        pageContainer.setScrollable(scrollable);
    }

    public ScrollPageView getLeftPageView(){
        return pageContainer.getLeftPageView();
    }

    public ScrollPageView getMiddlePageView(){
        return pageContainer.getMiddlePageView();
    }

    public ScrollPageView getRightPageView(){
        return pageContainer.getRightPageView();
    }

    public ScrollableLinearLayout getPageContainer() {
        return pageContainer;
    }

    private void init(Context context){
        isPageFirstShown = true;
        pageContainer = new ScrollableLinearLayout(context);
        pageContainer.setHorizontalScrollBarEnabled(true);
        pageContainer.setVerticalScrollBarEnabled(false);

        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.FILL_PARENT);
        addView(pageContainer, params);

        setTotalPages(3);
        showPage(1, false);
    }

//	private void showPage(int index, boolean anim) {
//		if(index < 0 || index > pages.size() - 1){
//			return;
//		}
//		curPageNumber = index;
//		int measureWidth = getMeasuredWidth();
//		if (0 != measureWidth) {
//			if (anim) {
//				int leftBarWidth = pageContainer.getLeftPageView().getWidth();
//				pageContainer.flingTo(leftBarWidth);
//			} else {
//				int leftBarWidth = pageContainer.getLeftPageView().getWidth();
//				pageContainer.scrollTo(leftBarWidth, pageContainer.getScrollY());
//			}
//		} else {
//			firstShownPageNumber = index;
//		}
//
//		if (isPageFirstShown && 0 == index) {
//			isPageFirstShown = false;
//			if (null != scrollListener) {
//				ScrollableLinearLayout pc = pageContainer;
//				int scrollX = pc.getScrollX();
//				int scrollY = pc.getScrollY();
//				scrollListener.onScrollChanged(scrollX, scrollY,
//						scrollX, scrollY);
//			}
//		}
//	}

    public ScrollPageView getPage(int index) {
        return pages.get(index);
    }


    @Override
    protected void onFinishInflate() {
        pageContainer.setAlwaysDrawnWithCacheEnabled(true);
        pageContainer.setAnimationCacheEnabled(true);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        pageContainer.layout(0, 0, r - l, b - t);
        if (isPageFirstShown) {
            isPageFirstShown = false;
            int i = firstShownPageNumber;
            int j = getMeasuredWidth();
            int k = i * j;
            int scrollY = pageContainer.getScrollY();
            pageContainer.scrollTo(k, scrollY);
        }
        if (changed) {
            showPage(curPageNumber,false);
        }
    }

    private void showPage(int index,boolean anim) {
        switch (index) {
            case 0:
                showLeftPageView(anim);
                break;
            case 2:
                showRightPageView(anim);
                break;
            default:
                showMiddlePageView(anim);
                break;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        if (MeasureSpec.EXACTLY == mode || MeasureSpec.AT_MOST == mode) {
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);
            Iterator<ScrollPageView> iterator = pages.iterator();
            int indexpage = 0;
            while (iterator.hasNext()) {

                ScrollPageView scrollablePageView = iterator.next();
                switch(indexpage)
                {
                case 0:
                    scrollablePageView.setPageDimension(LEFT_BAR_WIDTH, height);
                    scrollablePageView.setBackgroundDrawable(
                            getResources().getDrawable(R.drawable.background));
//                    scrollablePageView.setForeground(
//                            BrowserActivity.getDrawable(R.drawable.left_bg_shadow));
//                    scrollablePageView.setForegroundGravity(Gravity.CLIP_HORIZONTAL);
                    break;
                case 1:
                    scrollablePageView.setPageDimension(width, height);
                    break;
                case 2:
                    scrollablePageView.setPageDimension(RIGHT_BAR_WIDTH, height);
                    scrollablePageView.setBackgroundDrawable(
                            getResources().getDrawable(R.drawable.background));
//                    scrollablePageView.setForeground(
//                            BrowserActivity.getDrawable(R.drawable.right_bg_shadow));
//                    scrollablePageView.setForegroundGravity(Gravity.LEFT);
                    break;

                }
                indexpage++;
            }

            int size = pages.size();
            width *= size;
            int widthSpec = MeasureSpec.makeMeasureSpec(width,
                    MeasureSpec.EXACTLY);
            pageContainer.measure(widthSpec, heightMeasureSpec);
        }

        int width1 = MeasureSpec.getSize(widthMeasureSpec);
        int height1 = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width1, height1);
    }

    public void setPageEventObserver(PageEventObserver observer) {
        pageEventObserver = observer;
    }

    public void setTotalPages(int n) {
        int i = 0;
        Context context = getContext();
        while(pageContainer.getChildCount() > 0){
            ViewGroup view = (ViewGroup) pageContainer.getChildAt(0);
            view.removeAllViews();
            pageContainer.removeView(view);
        }
        pages.clear();
        while (i < n) {
            ScrollPageView scrollablePageView = new ScrollPageView(context);
            scrollablePageView.setDescendantFocusability(FOCUS_BEFORE_DESCENDANTS);
            scrollablePageView.setPageNumber(i);
            pageContainer.addView(scrollablePageView);
            pages.add(scrollablePageView);
            i++;
        }
    }

    public void showLeftPageView(boolean anim){
        curPageNumber = 0;
        ScrollPageView pageView = getLeftPageView();
        int count = pageView.getChildCount();
        if (0 == count) {
            pageProvider.requestLeftPage(pageView);
        }
        int measureWidth = getMeasuredWidth();
        if (0 != measureWidth) {
            if (anim) {
                pageContainer.flingTo(0);
            } else {
                pageContainer.scrollTo(0, 0);
            }
        } else {
            firstShownPageNumber = 0;
        }
        if(null != pageEventObserver){
            pageEventObserver.onLeftPageShown(pageView);
        }
    }

    public void showMiddlePageView(boolean anim){
        curPageNumber = 1;
        int measureWidth = getMeasuredWidth();
        if (0 != measureWidth) {
            int leftBarWidth = pageContainer.getLeftPageView().getWidth();
            if (anim) {
                pageContainer.flingTo(leftBarWidth);
            } else {
                pageContainer.scrollTo(leftBarWidth, 0);
            }
        } else {
            firstShownPageNumber = 1;
        }
        if(null != pageEventObserver){
            pageEventObserver.onMiddlePageShown(getMiddlePageView());
        }
    }

    public void showRightPageView(boolean anim){
        curPageNumber = 2;
        ScrollPageView pageView = getRightPageView();
        int count = pageView.getChildCount();
        if (0 == count) {
            pageProvider.requestRightPage(pageView);
        }
        int measureWidth = getMeasuredWidth();
        if (0 != measureWidth) {
            int to = pageContainer.getLeftPageView().getWidth() + pageContainer.getRightPageView().getWidth();
            if (anim) {
                pageContainer.flingTo(to);
            } else {
                pageContainer.scrollTo(to, 0);
            }
        } else {
            firstShownPageNumber = 2;
        }
        if(null != pageEventObserver){
            pageEventObserver.onRightPageShown(pageView);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        if (MotionEvent.ACTION_UP == action) {
        int scrollX = pageContainer.getScrollX();
            FlingableLinearLayout.FlingDirection direction = pageContainer.getFlingDirection();
            if (FlingableLinearLayout.FlingDirection.NONE == direction) {
                scrollToPage(scrollX);
            } else if (FlingableLinearLayout.FlingDirection.LEFT == direction) {
                int n = getRightPageNum(scrollX);
                if (1 == n) {
                    //仅在显示中间Page的时候才可以Fling
                    fingToPage(n);
                }
                else {
                    scrollToPage(scrollX);
                }
            } else {
                int n = getLeftPageNum(scrollX);
                if (1 == n) {
                    //仅在显示中间Page的时候才可以Fling
                    fingToPage(n);
                }
                else {
                    scrollToPage(scrollX);
                }
            }
        }
        return false;
    }

    private int getLeftPageNum(int scrollX) {
        return curPageNumber > 0 ? curPageNumber - 1 : curPageNumber;
    }

    private int getRightPageNum(int scrollX) {
        return curPageNumber < 2 ? curPageNumber + 1 : curPageNumber;
    }

    private void scrollToPage(int x) {
        int index = getPageIndex(x);
        curPageNumber = index;
        showPage(index, true);
    }

    private void fingToPage(int index) {
        curPageNumber = index;
        showPage(index, true);
    }

    private int getPageIndex(int scrollX){
        int leftBarWidth = getLeftPageView().getWidth();
        int rightBarWidth = getRightPageView().getWidth();

        if (scrollX <= leftBarWidth / 2) {
            return 0;
        }
        else if (scrollX > leftBarWidth / 2 && scrollX < leftBarWidth + rightBarWidth / 2) {
            return 1;
        }
        else {
            return 2;
        }
    }

    public int getCurrentPageIndex(){
        return curPageNumber;
    }

}
